#define DEBUG 1		// 1 during development 0 at other times

#include <stdio.h>
#include <portaudio.h>
#include <string.h>  // For "strdup()"
#include <libintl.h>  // For "gettext()"

#ifdef WIN32
#elif __BEOS__
#elif __APPLE__
#else
# include "sys/stat.h" // for mkdir()
# include "sys/time.h" // for gettimeofday()
#endif

#include "tp_magic_api.h"  // Tux Paint "Magic" tool API header
#include "SDL_image.h"  // For IMG_Load(), to load our PNG icon

#ifndef NOSOUND
# include "tp_sound.h"

enum
{
	TOOL_TEMPLATE,
	NUM_TOOLS
};


typedef struct {
	const char *icon_filename;
	const char *name;
	const char *desc;
} toolsstru;

toolsstru tools[NUM_TOOLS] = 
{
	{
		"memo-playbutton.png",
		gettext_noop ( "memo Play"),
		gettext_noop ( "Choose a play button to reproduce the sound previously recorded there."),
	}
};

#define SAMPLE_RATE  (44100)
#define FRAMES_PER_BUFFER (1024)
#define PA_SAMPLE_TYPE  paFloat32
#define SAMPLE_SILENCE  (0.0f)

typedef struct
{
    int          frameIndex;  /* Index into sample array. */
    tp_sound_recording* recording;
} paPlayData;

PaStream *stream;
paPlayData data;

static int playCallback( const void *inputBuffer, void *outputBuffer,
                         unsigned long framesPerBuffer,
                         const PaStreamCallbackTimeInfo* timeInfo,
                         PaStreamCallbackFlags statusFlags,
                         void *userData )
{
    paPlayData *data = (paPlayData*)userData;
    SAMPLE *rptr = &data->recording->samples[data->frameIndex];
    SAMPLE *wptr = (SAMPLE*)outputBuffer;
    unsigned int i;
    int finished;
    unsigned int framesLeft = data->recording->size - data->frameIndex;

    (void) inputBuffer; /* Prevent unused variable warnings. */
    (void) timeInfo;
    (void) statusFlags;
    (void) userData;

    if( framesLeft < framesPerBuffer )
    {
        /* final buffer... */
        for( i=0; i<framesLeft; i++ )
        {
            *wptr++ = *rptr++;  /* left */
        }
        for( ; i<framesPerBuffer; i++ )
        {
            *wptr++ = 0;  /* left */
        }
        data->frameIndex += framesLeft;
        finished = paComplete;
    }
    else
    {
        for( i=0; i<framesPerBuffer; i++ )
        {
            *wptr++ = *rptr++;  /* left */
        }
        data->frameIndex += framesPerBuffer;
        finished = paContinue;
    }
    return finished;
}


int memoplay(int x,int y){
	( void ) x;	
	( void ) y;
	// get the recording
	data.frameIndex = 0;
	data.recording = tp_sound_recording_in_coordinates(x,y,21);
	if(data.recording){
		// initialize port audio needed variables
		PaStreamParameters outputParameters;
	    	PaError err;
	
		outputParameters.device = Pa_GetDefaultOutputDevice(); /* default output device */
		outputParameters.channelCount = 1;                     /* stereo output */
		outputParameters.sampleFormat =  PA_SAMPLE_TYPE;
		outputParameters.suggestedLatency = Pa_GetDeviceInfo( outputParameters.device )->defaultLowOutputLatency;
		outputParameters.hostApiSpecificStreamInfo = NULL;
	
	    	err = Pa_OpenStream(
			&stream,
			NULL, /* no input */
			&outputParameters,
			SAMPLE_RATE,
			FRAMES_PER_BUFFER,
         		paClipOff,      /* we won't output out of range samples so don't bother clipping them */
			playCallback,
			&data );

		// start port audio stream
    		err = Pa_StartStream( stream );
	
		// stop stream
	        while( ( err = Pa_IsStreamActive( stream ) ) == 1 ) Pa_Sleep(100);
	        
	        err = Pa_CloseStream( stream );
	}	
#ifdef DEBUG
	fprintf( stderr, "memoplay_playing\n");
#endif
	return 0;
}

/* --------------------- */
Uint32 memoplay_api_version ( void )
{
#ifdef DEBUG
	fprintf( stderr, "memoplay_api_version\n");
#endif
	return TP_MAGIC_API_VERSION;
}

int memoplay_init ( magic_api * api )
{
	/* Prevent unused variable warnings. */
	( void ) api;	

#ifdef DEBUG
	fprintf( stderr, "memoplay_init\n");
#endif
	
	PaError err;
    	err = Pa_Initialize();
	if( err != paNoError ){
		printf("PortAudio error: %s\n", Pa_GetErrorText( err )); 
	}

	return 1;
}


/* --------------------- */
int memoplay_get_tool_count ( magic_api * api )
{
	/* Prevent unused variable warnings. */
	( void ) api;	

#ifdef DEBUG
	fprintf( stderr, "memoplay_get_tool_count\n");
#endif
	return NUM_TOOLS;
}


/* --------------------- */
SDL_Surface * memoplay_get_icon ( magic_api * api, int which )
{
	/* Prevent unused variable warnings. */
	( void ) api;	

	SDL_Surface *image;
	char fname[4096];

#ifdef DEBUG
	fprintf( stderr, "memoplay_get_icon\n");
#endif

	snprintf ( fname, sizeof ( fname ), "%s/images/magic/%s",
	           api->data_directory, tools[which].icon_filename );
#ifdef DEBUG
	fprintf( stderr, "DEBUG: Loading image %s\n", fname);
#endif

	image = IMG_Load ( fname );
	if(!image) {
		fprintf(stderr, "IMG_Load( %s): %s\n", fname, IMG_GetError());
	}
	return image;
}


/* --------------------- */
char * memoplay_get_name ( magic_api * api, int which )
{
	/* Prevent unused variable warnings. */
	( void ) api;	

	const char * our_name_english;
	const char * our_name_localized;

#ifdef DEBUG
	fprintf( stderr, "memoplay_get_name\n");
#endif
	our_name_english = tools[which].name;
	our_name_localized = gettext ( our_name_english );
	return strdup ( our_name_localized );
}

/* --------------------- */
char * memoplay_get_description ( magic_api * api, int which, int mode )
{
	/* Prevent unused variable warnings. */
	( void ) api;	
	( void ) mode;

	const char * our_desc_english;
	const char * our_desc_localized;

#ifdef DEBUG
	fprintf( stderr, "memoplay_get_description\n");
#endif
	our_desc_english = tools[which].desc;
	our_desc_localized = gettext ( our_desc_english );
	return strdup ( our_desc_localized );
}

/* --------------------- */
int memoplay_requires_colors ( magic_api * api, int which )
{
	/* Prevent unused variable warnings. */
	( void ) api;	
	( void ) which;
	return 0;	// FALSE
}

/* --------------------- */
int memoplay_modes ( magic_api * api, int which )
{
	/* Prevent unused variable warnings. */
	( void ) api;	
	( void ) which;

	return MODE_FULLSCREEN;
}


// Shut down
//
// explain how SDL_audioin could be patched to make Open/CloseAudioIn work
// symmetrically for the DEVDSP (Linux) driver

/* --------------------- */
void memoplay_shutdown ( magic_api * api )
{
	/* Prevent unused variable warnings. */
	( void ) api;	

#ifdef DEBUG
	fprintf( stderr, "memoplay_shutdown\n");
#endif
	// Terminate PortAudio
	PaError err;
	err = Pa_Terminate();
	if( err != paNoError )
	   printf(  "PortAudio error: %s\n", Pa_GetErrorText( err ) );
}


/* --------------------- */
void memoplay_click ( magic_api * api, int which, int mode,
                     SDL_Surface * canvas, SDL_Surface * snapshot,
                     int x, int y, SDL_Rect * update_rect )
{
	/* Prevent unused variable warnings. */
	( void ) api;	
	( void ) canvas;
	( void ) snapshot;
	( void ) which;
	( void ) mode;
	( void ) update_rect;

#ifdef DEBUG
	fprintf( stderr, "memoplay_click\n");
#endif
	memoplay(x,y);
}


/* --------------------- */
void memoplay_drag ( magic_api * api, int which, SDL_Surface * canvas,
                    SDL_Surface * snapshot, int ox, int oy, int x, int y,
                    SDL_Rect * update_rect )
{
	/* Prevent unused variable warnings. */
	( void ) api;
	( void ) canvas;
	( void ) snapshot;
	( void ) which;
	( void ) ox;
	( void ) oy;
	( void ) x;
	( void ) y;
	( void ) update_rect;
#ifdef DEBUG
	fprintf( stderr, "memoplay_drag\n");
#endif
}


/* --------------------- */
void memoplay_release ( magic_api * api, int which,
                       SDL_Surface * canvas, SDL_Surface * snapshot,
                       int x, int y, SDL_Rect * update_rect )
{
	/* Prevent unused variable warnings. */
	( void ) api;
	( void ) canvas;
	( void ) snapshot;
	( void ) which;
	( void ) x;
	( void ) y;
	( void ) update_rect;
#ifdef DEBUG
	fprintf( stderr, "memoplay_release\n");

#endif
}


/* --------------------- */
void memoplay_set_color ( magic_api * api, Uint8 r, Uint8 g, Uint8 b )
{
	/* Prevent unused variable warnings. */
	( void ) api;
	( void ) r;
	( void ) g;
	( void ) b;

	// this tool uses no color
}

/* --------------------- */
void memoplay_switchin ( magic_api * api, int which, int mode, SDL_Surface * canvas )
{
	/* Prevent unused variable warnings. */
	( void ) api;
	( void ) canvas;
	( void ) which;
	( void ) mode;
	
#ifdef DEBUG
	fprintf( stderr, "memoplay_sSDL_UpdateRectwitchin\n");
#endif
	return;
}

/* --------------------- */
void memoplay_switchout ( magic_api * api, int which, int mode, SDL_Surface * canvas )
{
	/* Prevent unused variable warnings. */
	( void ) api;
	( void ) canvas;
	( void ) which;
	( void ) mode;

	// destroy the canvas

#ifdef DEBUG
	fprintf( stderr, "memoplay_switchout\n");
#endif
	return;
}
#endif // NOSOUND endif
